<template>
  <div class="AAE_module">
    <module-header
      :title="title"
      :meter="meter"
      :params="{
        module: 'AAE',
        status: selectRecordStatus,
        Id: selectRecordId,
        Bore: init_main_params.AAF701
      }"
    />
    <section class="message">
      <div class="item">
        <span>出厂编号</span>
        <el-input size="mini" v-model="init_main_params.AAF001" disabled placeholder="请输入" />
      </div>
      <div class="item">
        <span>通径</span>
        <el-select size="mini" v-model="init_main_params.AAF701" disabled></el-select>
      </div>
      <div class="item">
        <span>转换器型号</span>
        <el-select size="mini" v-model="init_main_params.AAF1301" disabled></el-select>
      </div>
    </section>
    <section class="table">
      <record-table
        title="第三方记录表"
        procedure="AAE"
        :meter="meter"
        :params="{
          title,
          Cutting: ''
        }"
        :tableData="tableData"
        :limits="RecordTableLimit"
        :tableColumnDict="tableColumnDict"
        @onRecordSelect="onRecordSelect"
        @onRecordStore="onRecordStore"
        @onRecordDelete="onRecordDelete"
      />
    </section>
    <section class="settings">
      <div class="setting-header">
        <h4>历史数据分析</h4>
        <div class="buttons">
          <!-- 导入原始数据 -->
          <el-upload
            class="upload-demo"
            action=""
            accept=".xls, .xlsx, .csv"
            :disabled="selectRecordId === ''"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="readLocaleExcel"
          >
            <el-tooltip
              class="item"
              :effect="theme === 'light' ? 'dark' : 'light'"
              content="导入原始数据"
              placement="top"
            >
              <i :class="['iconfont icon-addcell', selectRecordId === '' ? 'is-disabled' : '']" />
            </el-tooltip>
          </el-upload>
          <!-- 修改IP -->
          <!-- <el-tooltip
            class="item"
            :effect="theme === 'light' ? 'dark' : 'light'"
            content="修改IP"
            placement="top"
          >
            <i class="iconfont icon-to-do" />
          </el-tooltip> -->
          <!-- 显示弹框 -->
          <el-tooltip
            class="item"
            :effect="theme === 'light' ? 'dark' : 'light'"
            content="显示弹框"
            placement="top"
          >
            <i
              :class="['iconfont', !isPopoverShow ? 'icon-not_visible' : 'icon-visible']"
              @click="isPopoverShow = true"
            />
          </el-tooltip>
          <!-- 图表分析 -->
          <el-tooltip
            class="item"
            :effect="theme === 'light' ? 'dark' : 'light'"
            content="图表分析"
            placement="top"
          >
            <i
              :class="{
                'iconfont icon-charts-bar': true,
                'is-disabled': selectRecordId === '' || !originTableData.length
              }"
              @click="handleChartOpen"
            />
          </el-tooltip>
        </div>
      </div>
      <div class="setting-body">
        <div class="column column-setting">
          <task-tab
            ref="tab"
            :settings="AAE_ChannelSettings"
            :disabled="selectRecordId === ''"
            @change="onTaskTabChange"
          />
        </div>
        <div class="column column-table">
          <el-table
            :data="OriginTableDataFrame"
            v-loading="isTableLoading"
            border
            stripe
            height="330"
            size="mini"
            style="width: 100%"
            :cell-style="computeBgColorByTimeRange"
            @row-click="onTableRowClick"
            @row-contextmenu="onRowOpenContextmenu"
          >
            <el-table-column
              v-for="column in defaultTableColumn"
              :key="column"
              :prop="column"
              :label="column"
              min-width="120"
            />
          </el-table>
          <el-pagination
            small
            background
            layout="total, prev, pager, next"
            :total="originTableData.length"
            :page-size="pageSize"
            :current-page.sync="currentPage"
            @current-change="handleCurrentChange"
          />
        </div>
        <div ref="lastColumn" class="column">
          <div class="row">
            <span>分析结论：</span>
            <span :class="ErrorStatus">{{ errorRecords.AAE801 ? errorRecords.AAE801 : '无' }}</span>
          </div>
          <div class="row">
            <div class="title">概况</div>
            <el-input
              v-model="errorRecords.AAE1001"
              type="textarea"
              :rows="4"
              resize="none"
              :autosize="false"
            />
          </div>
          <div class="row" :style="{ height: labelsHeight + 'px' }">
            <div class="title">错误数据</div>
            <div class="labels">
              <div v-for="(label, index) in ErrorData" :key="index" class="label">
                <span v-for="(v, k) in label" :key="k">{{ k.toString().slice(2) }}: {{ v }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
    <!-- 原始数据表格 & 计算结果表格 -->
    <transition name="opacity">
      <section v-if="isPopoverShow" class="popover">
        <div class="popover-content" v-clickoutside="() => (isPopoverShow = false)">
          <div class="row">
            <div class="title">源数据</div>
            <div class="table">
              <el-table
                :data="OriginTableDataFrame"
                size="mini"
                stripe
                :height="300"
                :cell-style="computeBgColorByTimeRange"
                @row-click="onTableRowClick"
              >
                <el-table-column
                  v-for="column in OriginTableColumn"
                  :key="column"
                  :prop="column"
                  :label="column"
                  width="150"
                  style="width: 100%"
                >
                  <template v-slot:header>
                    <el-checkbox-group
                      v-model="defaultTableColumn"
                      @change="sortDefaultTableColumn"
                    >
                      <el-checkbox :label="column" :key="column">{{ column }}</el-checkbox>
                    </el-checkbox-group>
                  </template>
                </el-table-column>
              </el-table>
            </div>
            <div class="footer">
              <el-pagination
                background
                layout="total, prev, pager, next"
                :total="originTableData.length"
                :page-size="pageSize"
                :current-page.sync="currentPage"
                @current-change="handleCurrentChange"
              />
            </div>
          </div>
          <div class="row">
            <div class="title">分析结果</div>
            <div class="table">
              <el-table
                ref="resultTable"
                :data="analysisData"
                size="mini"
                stripe
                :height="300"
                :cell-style="computeResultTableStyle"
                @cell-click="onResultTableClick"
              >
                <el-table-column
                  v-for="column in ResultTableColumn"
                  :key="column"
                  :prop="column"
                  :label="column"
                  :fixed="column === '项目'"
                  width="150"
                  style="width: 100%"
                />
              </el-table>
            </div>
          </div>
        </div>
      </section>
    </transition>
    <!-- 原始数据表格行具体数据 -->
    <transition name="opacity">
      <section
        v-if="isPreviewAreaShow"
        :style="previewAreaPosition"
        class="preview-area"
        v-clickoutside="() => (isPreviewAreaShow = false)"
      >
        <div v-for="(value, key) in previewAreaLabels" :key="key" class="label-container">
          <span>{{ key }}</span>
          <span>{{ value }}</span>
        </div>
      </section>
    </transition>
    <!-- 原始数据表格图例 -->
    <transition name="opacity">
      <section v-if="isPopoverChartShow" class="popover">
        <div class="popover-content chart" v-clickoutside="() => (isPopoverChartShow = false)">
          <basic-line class="basic-line" :xAxis="xAxisData" :series="seriesData" />
          <el-checkbox-group
            class="checkbox-group"
            v-model="defaultTableColumn"
            @change="sortDefaultTableColumn"
          >
            <el-checkbox v-for="status in OriginTableColumn.slice(1)" :label="status" :key="status">
              {{ status }}
            </el-checkbox>
          </el-checkbox-group>
        </div>
      </section>
    </transition>
  </div>
</template>

<script lang="ts">
import Vue, { ComponentInstance } from 'vue'
import { Getter } from 'vuex-class'
import { Component, Prop, Ref, Watch } from 'vue-property-decorator'
import { AxiosResponse } from 'axios'
import { Dictionary, SettingType } from '@/interface/Basic'
import { SelectOptionsType } from '@/interface/ElementUI'
import XLSX from 'xlsx'
import RecordTable from '@/components/basic/RecordTable.vue'
import TaskTab from '@/views/dashboard/compoents/TaskTab.vue'
import ModuleHeader from '@/components/basic/ModuleHeader.vue'
import { Message } from 'element-ui'
import BasicLine from './basic_line.vue'
import { GetProcedureRecordData, UpdateProcedureRecord } from '@/api/procedure'
import { AAE_GetConfiguration, AAE_AnalysisData, AAE_GetRawData, AAE_SaveRawData } from '@/api/AAE'
import {
  tableColumnDict,
  TableColumnType,
  AAE_ChannelSettings,
  HistoryTableColumn,
  ResultTableColumn
} from './params'
import {
  GetInitialParams,
  GenerateCurPageLimits,
  FillInTaskTabData,
  FillInTaskTabOptions,
  CaptureTaskTabData
} from '@/utils/precedure'
import { deepClone, formatTime } from '@/utils/specificFunc'
import { ElTableColumn } from 'element-ui/types/table-column'
interface ConfigurationType {
  filename: string
  standards: {
    standard: string
    bindingValue: Dictionary<string>
  }[]
}
interface AnalysisResultType {
  AAE801: string
  AAE1001: string
  ERRdata: Dictionary<string>[]
  Alldata: Dictionary<string>[]
}
@Component({
  components: {
    TaskTab,
    RecordTable,
    ModuleHeader,
    BasicLine
  }
})
class NoneStandard extends Vue {
  @Getter('name') username!: string
  @Getter('theme') theme!: 'light' | 'dark'
  @Getter('sidebar') sidebar!: { opened: boolean }
  @Ref() lastColumn!: HTMLElement
  @Ref() tab!: { captureSettings: () => Dictionary<string> }
  @Ref() resultTable!: ComponentInstance
  @Prop() status!: string
  @Prop({ default: '' }) meter!: string
  @Prop({ required: true }) title!: string
  mounted() {
    this.initDashboardParams()
    this.animateLabelsHeight()
    AAE_GetConfiguration().then(config => {
      this.configurations = config.data.ReturnData
    })
  }
  /** 主页面数据 */
  init_main_params: Dictionary<string> = {
    AAF001: '',
    AAF701: '',
    AAF1301: ''
  }
  initDashboardParams() {
    const main_params: Dictionary<string> = {
      AAF001: '',
      AAF701: '',
      AAF1301: ''
    }
    GetInitialParams(this.meter, main_params).then(res => {
      this.init_main_params = res.params
    })
  }
  getAvailableItem<T>(dict: Dictionary<T>) {
    let availableItem: '保存时间' | '日期' = '保存时间'
    const { 保存时间: saveTime, 日期: saveDate } = dict
    if (saveDate) availableItem = '日期'
    if (saveTime) availableItem = '保存时间'
    return availableItem
  }
  /** 操作记录表 */
  tableColumnDict = tableColumnDict
  tableData: TableColumnType[] = []
  selectRecordId: string = ''
  selectRecordStatus: string = ''
  init_button_limit: Dictionary<boolean> = {
    // 保存
    AAE_0: false,
    // 删除
    AAE_1: false,
    // 新建
    AAE_2: true,
    // 导入数据源
    AAE_3: true,
    // 历史数据分析
    AAE_4: true,
    // 改IP
    AAE_5: false
  }
  get RecordTableLimit(): Dictionary<boolean> {
    const { AAE_0, AAE_1, AAE_2 } = this.init_button_limit
    return {
      Store: AAE_0,
      Create: AAE_2,
      Delete: AAE_1
    }
  }
  initButtonsLimit(limits: string) {
    GenerateCurPageLimits(limits, 'AAE', this.init_button_limit).then(limit => {
      this.init_button_limit = limit
    })
  }
  onRecordSelect(data: Dictionary<string>) {
    const { id, status, DatabaseLabel } = data
    this.selectRecordId = id
    this.selectRecordStatus = status
    GetProcedureRecordData({ id, DatabaseLabel }).then(
      (res: AxiosResponse<{ ReturnData: Dictionary<string> }>) => {
        const { ReturnData } = res.data
        this.records = ReturnData
        const { AAE801, AAE1001 } = ReturnData
        this.errorRecords = { AAE801, AAE1001 }
        this.initButtonsLimit(ReturnData.AAE002)
        this.AAE_ChannelSettings = FillInTaskTabData(this.AAE_ChannelSettings, ReturnData)
        this.config_handler(this.configurations)
        this.isTableLoading = true
        this.indexRangeForCalculate = {
          start_index: null,
          end_index: null,
          start_date_time: null,
          end_date_time: null
        }
        // 获取存储的原始数据接口
        AAE_GetRawData({ number: this.meter, time: ReturnData.AAE701 }).then(
          (response: AxiosResponse<{ ReturnData: Dictionary<string>[] }>) => {
            const data = response.data.ReturnData.map(item => {
              const obj: Dictionary<string> = {}
              Object.keys(item).forEach(key => {
                obj[key.trim()] = item[key]
              })
              return obj
            })
            this.updateOriginTableData(data)
            this.isTableLoading = false
            if (data.length === 0) return
            const availableItem = this.getAvailableItem(data[0])
            this.indexRangeForCalculate = {
              start_index: 0,
              start_date_time: new Date(data[0][availableItem]).getTime(),
              end_index: data.length,
              end_date_time: new Date(data[data.length - 1][availableItem]).getTime()
            }
            this.startAnalysisData()
          }
        )
      }
    )
  }
  onRecordDelete() {
    this.selectRecordId = ''
    this.selectRecordStatus = ''
  }
  onRecordStore(params: Dictionary<string>) {
    if (params.DatabaseLabel !== 'AAE') return
    if (!params.id) {
      Message({
        type: 'warning',
        message: '未选中id，无法保存'
      })
      return
    }
    const params_AAE: Dictionary<string> = {
      Process: this.title
    }
    const tabSettings = this.tab.captureSettings()
    const errorSettings = this.errorRecords
    const Details: Dictionary<string> = deepClone({
      ...this.records,
      ...tabSettings,
      ...errorSettings
    })
    Details.AAE1801 = params.Status
    Details.AAE1701 = params_AAE.Process
    Details.AAE901 = this.username
    Details.AAE701 = formatTime(new Date().getTime(), 'YYYY-MM-DD-hh-mm-ss')
    const total_params = { ...params, ...params_AAE, ...{ Details } }
    UpdateProcedureRecord(total_params).then((res: AxiosResponse<{ Message: string }>) => {
      this.$message({
        type: 'success',
        message: res.data.Message
      })
      const { start_index, end_index } = this.indexRangeForCalculate
      if (start_index === null || end_index === null) return
      const tableFrame = this.originTableData
        .slice(start_index, end_index)
        .reverse() as Dictionary<string>[]
      const saveParams = {
        dt: tableFrame,
        AAE001: this.meter,
        id: this.selectRecordId
      }
      AAE_SaveRawData(saveParams).then(sec_res => {
        this.$message({
          type: 'success',
          message: sec_res.data.Message
        })
        // this.selectRecordId = ''
        // this.selectRecordStatus = ''
        this.$broadEmit('onRecordStoreSucceed', { procedure: this.title })
      })
    })
  }
  /** task-tab 组件 传递给 task-tab 组件的配置项 */
  AAE_ChannelSettings = AAE_ChannelSettings
  configurations: ConfigurationType[] = []
  get OriginTableDataFrame() {
    return this.originTableData.slice(
      (this.currentPage - 1) * this.pageSize,
      this.currentPage * this.pageSize
    )
  }
  @Watch('configurations', { deep: true })
  config_handler(newVal: ConfigurationType[]) {
    const AAE401_options: SelectOptionsType<string> = newVal.map(item => {
      return { label: item.filename, value: item.filename }
    })
    const AAE1301_options = this.GetAAE1301Options()
    this.AAE_ChannelSettings = FillInTaskTabOptions(this.AAE_ChannelSettings, {
      AAE401: AAE401_options,
      AAE1301: AAE1301_options
    })
  }
  // 监听到 tasktab 组件绑定数据发生改变后，需要实时更新下拉选项
  // 该函数会在页面初始化以及【AAE401】配置文件发生变化时触发，获取【AAE1301】数据标准的配置选项
  GetAAE1301Options() {
    let AAE1301_options: SelectOptionsType<string> = []
    const row_AAE401 = this.AAE_ChannelSettings.find(row => row.key === 'AAE401')
    // 判断此时用户是否已经选中 AAE401 的值，未选中返回空数组
    if (row_AAE401 && row_AAE401.value) {
      const selected_config = this.configurations.find(
        config => config.filename === row_AAE401.value
      )
      // 选项中存在选中的文件名，基于该值更新 AAE1301 的配置选项
      if (selected_config) {
        AAE1301_options = selected_config.standards.map(item => {
          return { label: item.standard, value: item.standard }
        })
      } else {
        // 不存在，说明现场调整过配置文件，弹出提示信息
        Message({
          type: 'warning',
          message: '【配置文件】选项内没有当前值，请检查有无调整'
        })
      }
    }
    return AAE1301_options
  }
  // 当 AAE1301 的值发生变化时，将 configurations 内符合条件的 bindingValue 填入 tasktab 组件内
  UpdateTabsValue(dict: Dictionary<string>) {
    const { AAE401, AAE1301 } = dict
    this.configurations.forEach(item => {
      if (item.filename === AAE401) {
        const selected = item.standards.find(standard => standard.standard === AAE1301)
        if (selected) {
          const { actualTime, unitAmp, comparSVofErr } = selected.bindingValue
          this.AAE_ChannelSettings = FillInTaskTabData(this.AAE_ChannelSettings, {
            AAE1501: actualTime,
            AAE1601: unitAmp,
            AAE1101: comparSVofErr
          })
        }
      }
    })
  }
  onTaskTabChange(e: { item: SettingType; dict: Dictionary<string> }) {
    const { item, dict } = e
    this.AAE_ChannelSettings = FillInTaskTabData(this.AAE_ChannelSettings, dict)
    if (item.key === 'AAE401') {
      const AAE1301_options = this.GetAAE1301Options()
      const hasOption = AAE1301_options.find(option => option.label === dict.AAE1301)
      // 已填入数据，但下拉框内没有响应的选项
      if (dict.AAE1301 !== '' && !hasOption) {
        Message({
          type: 'warning',
          message: '【数据标准】选项内没有当前值，请检查有无调整'
        })
      } else {
        this.UpdateTabsValue(dict)
      }
      this.AAE_ChannelSettings = FillInTaskTabOptions(this.AAE_ChannelSettings, {
        AAE1301: AAE1301_options
      })
    } else if (item.key === 'AAE1301') {
      this.UpdateTabsValue(dict)
    }
  }
  /** 原始数据表格组件 */
  // popover
  currentPage: number = 1
  pageSize: number = 20
  isPopoverShow: boolean = false
  isTableLoading: boolean = false
  // preview area
  isPreviewAreaShow: boolean = false
  previewAreaPosition: Dictionary<string> = {}
  previewAreaLabels: Dictionary<string | number> = {}
  OriginTableColumn = HistoryTableColumn
  defaultTableColumn = HistoryTableColumn.slice(0, 5)
  originTableData: Dictionary<number | string | Date>[] = []
  indexRangeForCalculate: Dictionary<number | null> = {
    start_index: null,
    end_index: null,
    start_date_time: null,
    end_date_time: null
  }
  sortDefaultTableColumn() {
    const origin = deepClone(this.OriginTableColumn)
    const target = deepClone(this.defaultTableColumn)
    const res: string[] = new Array(origin.length).fill('')
    target.forEach(column => {
      const idx = origin.findIndex(o_column => o_column === column)
      if (idx || idx === 0) {
        res[idx] = column
      }
    })
    this.defaultTableColumn = res.filter(item => item !== '')
  }
  onTableRowClick(row: Dictionary<string>) {
    const { AAE1501 } = this.tab.captureSettings()
    if (!AAE1501 || isNaN(Number(AAE1501))) {
      Message({
        type: 'warning',
        message: '实际时间数据为空或不合法，无法获取'
      })
      return
    }
    const availableItem = this.getAvailableItem(row)
    let start_idx = 0
    let end_idx = 0
    const click_row_date = new Date(row[availableItem]).getTime()
    const start_time = click_row_date - Number(AAE1501) * 60 * 1000
    const valid_time_range: number[] = [start_time - 60 * 1000, start_time + 60 * 1000]
    this.originTableData.forEach((row, index) => {
      const cur_row_date = new Date(row[availableItem]).getTime()
      if (cur_row_date === click_row_date) {
        start_idx = index
        // 方便用户选择最近的记录，originTableData 作了翻转处理，起始索引代表结束时间 | 结束索引代表起始时间
        this.indexRangeForCalculate.start_index = start_idx
        this.indexRangeForCalculate.end_date_time = cur_row_date
        this.AAE_ChannelSettings = FillInTaskTabData(this.AAE_ChannelSettings, {
          AAE501: formatTime(cur_row_date, 'YYYY-MM-DD-hh-mm-ss')
        })
      }
      if (index < this.originTableData.length - 1) {
        const next_row_date = new Date(this.originTableData[index + 1][availableItem]).getTime()
        if (
          cur_row_date >= valid_time_range[0] &&
          cur_row_date <= valid_time_range[1] &&
          next_row_date < valid_time_range[0]
        ) {
          end_idx = index
          this.indexRangeForCalculate.end_index = end_idx + 1
          this.indexRangeForCalculate.start_date_time = cur_row_date
          this.AAE_ChannelSettings = FillInTaskTabData(this.AAE_ChannelSettings, {
            AAE601: formatTime(cur_row_date, 'YYYY-MM-DD-hh-mm-ss')
          })
        }
      }
    })
    if (end_idx === 0) {
      Message({
        type: 'error',
        message: '未查询到合法的结束范围，计算失败'
      })
      return
    }
    this.startAnalysisData()
  }
  // onTableMouseEnter(...rest: any[]) {
  //   const result: Dictionary<string> = {}
  //   const row: Dictionary<string | number> = rest.at(0)
  //   const { width, height, left, top } = (rest.at(2) as HTMLElement).getBoundingClientRect()
  //   const offsetX = this.sidebar.opened ? 300 : 54
  //   result.left = left - offsetX + width + 'px'
  //   if (top + height + 300 > window.innerHeight) {
  //     result.top = top + height / 2 - 300 + 'px'
  //   } else {
  //     result.top = top + height / 2 + 'px'
  //   }
  //   this.isPreviewAreaShow = true
  //   this.previewAreaPosition = result
  //   this.previewAreaLabels = row
  // }
  onRowOpenContextmenu(...rest: any[]) {
    const result: Dictionary<string> = {}
    const row: Dictionary<string | number> = rest.at(0)
    const event = rest.at(2) as PointerEvent
    event.preventDefault()
    const target = event.target as HTMLElement
    if (!target) return
    const { width, height, left, top } = target.getBoundingClientRect()
    const offsetX = this.sidebar.opened ? 300 : 54
    result.left = left - offsetX + width + 'px'
    if (top + height + 300 > window.innerHeight) {
      result.top = top + height / 2 - 300 + 'px'
    } else {
      result.top = top + height / 2 + 'px'
    }
    this.isPreviewAreaShow = true
    this.previewAreaPosition = result
    this.previewAreaLabels = row
  }
  handleCurrentChange(current: number) {
    this.currentPage = current
  }
  computeBgColorByTimeRange(e: { row: Dictionary<string> }) {
    const availableItem = this.getAvailableItem(e.row)
    const cur_date_time = new Date(e.row[availableItem]).getTime()
    const { start_date_time, end_date_time } = this.indexRangeForCalculate
    if (start_date_time === null || end_date_time === null) return
    if (cur_date_time >= start_date_time && cur_date_time <= end_date_time) {
      return {
        color: '#FFFFFF',
        backgroundColor: this.theme === 'dark' ? '#09B1EC' : '#82C2E6'
      }
    }
  }
  /** 原始数据图表演示功能 */
  isPopoverChartShow: boolean = false
  xAxisData: string[] = []
  seriesData: Dictionary<number[]> = {}
  @Watch('defaultTableColumn', { deep: true })
  columns_handler() {
    this.generateBasicLineData()
  }
  updateOriginTableData(arr: Dictionary<any>[]) {
    const copiedArr = deepClone(arr)
    if (copiedArr.length !== 0) {
      this.OriginTableColumn = Object.keys(copiedArr[0])
      this.defaultTableColumn = this.OriginTableColumn.slice(0, 5)
    }
    this.originTableData = copiedArr.reverse()
  }
  // 读取本地文件，如果已有数据，则全部替换
  readLocaleExcel(e: { name: string; raw: File }) {
    this.isTableLoading = true
    const fileReader = new FileReader()
    fileReader.onload = ev => {
      try {
        const data = ev.target!.result
        const workbook = XLSX.read(data, {
          type: 'binary',
          cellDates: true,
          codepage: 936
        })
        const wsname = workbook.SheetNames
        const ws: Dictionary<string | Date>[] = XLSX.utils.sheet_to_json(
          workbook.Sheets[wsname[0]],
          {
            defval: null
          }
        )
        const availableItem = this.getAvailableItem(ws[0])
        for (let i = 0; i < ws.length; i++) {
          ws[i][availableItem] = formatTime(ws[i][availableItem].toString(), 'YYYY-MM-DD-hh-mm-ss')
        }
        this.updateOriginTableData(ws)
        this.isTableLoading = false
      } catch {
        return false
      }
    }
    fileReader.readAsBinaryString(e.raw)
  }
  handleChartOpen() {
    if (!this.originTableData.length) return
    this.isPopoverChartShow = true
    this.generateBasicLineData()
  }
  generateBasicLineData() {
    if (!this.originTableData.length) return
    const copiedData = deepClone(this.originTableData)
    const columns = deepClone(this.defaultTableColumn)
    let availableItem: '保存时间' | '日期' = '保存时间'
    if (columns.includes('日期')) availableItem = '日期'
    if (columns.includes('保存时间')) availableItem = '保存时间'
    const saveTimeIdx = columns.findIndex(column => column === availableItem)
    if (saveTimeIdx || saveTimeIdx === 0) {
      columns.splice(saveTimeIdx, 1)
    }
    const xAxis_arr: string[] = []
    const series_obj: Dictionary<number[]> = {}
    copiedData.forEach(row => {
      const saveTime = row[availableItem].toString()
      xAxis_arr.unshift(saveTime)
      columns.forEach(column => {
        if (!series_obj[column]) series_obj[column] = []
        series_obj[column].unshift(Number(row[column]))
      })
    })
    this.xAxisData = xAxis_arr
    this.seriesData = series_obj
  }
  /** 历史数据分析 */
  // 数据分析结果的列名集合
  ResultTableColumn = ResultTableColumn
  analysisData: Dictionary<string>[] = []
  records: Dictionary<string> = {}
  errorRecords: Dictionary<string> = {
    AAE801: '',
    AAE1001: ''
  }
  get ErrorStatus() {
    const { AAE801 } = this.errorRecords
    if (AAE801 === '') return 'isEmpty'
    else if (AAE801 === '不合格') return 'isError'
    else return 'isSuccess'
  }
  // labels container
  ErrorData: Dictionary<string>[] = []
  labelsHeight: number = 0
  relatedErrRowIndex: number[] = []
  relatedErrColumnLabel: string = ''
  animateLabelsHeight() {
    let { height: total_height } = this.lastColumn.getBoundingClientRect()
    for (let i = 0; i < 2; i++) {
      const { height } = (this.lastColumn.childNodes[i] as HTMLElement).getBoundingClientRect()
      total_height -= height
    }
    this.labelsHeight = total_height
  }
  startAnalysisData() {
    const { start_index, end_index } = this.indexRangeForCalculate
    if (start_index === null || end_index === null) return
    const dt = this.originTableData
      .slice(start_index, end_index)
      .map(row => {
        Object.keys(row).forEach(key => {
          row[key] = row[key].toString()
        })
        return row as Dictionary<string>
      })
      .reverse()
    const res = CaptureTaskTabData(this.AAE_ChannelSettings)
    AAE_AnalysisData({ ...{ dt }, ...res }).then(
      (res: AxiosResponse<{ ReturnData: AnalysisResultType }>) => {
        const { AAE801, AAE1001, ERRdata, Alldata } = res.data.ReturnData
        this.errorRecords = { AAE801, AAE1001 }
        this.ErrorData = ERRdata
        this.ResultTableColumn = Object.keys(Alldata[0])
        this.analysisData = Alldata
      }
    )
  }
  computeResultTableStyle(e: { row: Dictionary<string>; rowIndex: number; column: ElTableColumn }) {
    const { row, rowIndex, column } = e
    if (this.relatedErrRowIndex.includes(rowIndex) && column.label === this.relatedErrColumnLabel) {
      return {
        color: '#ffffff',
        backgroundColor: this.theme === 'dark' ? '#09B1EC' : '#82C2E6'
      }
    }
    const errorCell = this.ErrorData.find(
      item => item['错误行'] === row['项目'] && item['错误列'] === column.label
    )
    if (errorCell) {
      return {
        color: '#ffffff',
        backgroundColor: this.theme === 'dark' ? '#EC061D' : '#ED555A'
      }
    }
  }
  onResultTableClick(row: Dictionary<string>, column: ElTableColumn) {
    const rowLabel: string = row['项目']
    const columnLabel: string = column.label
    const errorCell = this.ErrorData.find(
      item => item['错误行'] === rowLabel && item['错误列'] === columnLabel
    )
    if (!errorCell) return
    const targetIndexes: number[] = this.analysisData.reduce((indexes, item, index) => {
      if (item['项目'].indexOf(rowLabel) !== -1 && item['项目'] !== rowLabel) {
        indexes.push(index)
      }
      return indexes
    }, [] as number[])
    if (!targetIndexes.length) return
    const resultTable = this.resultTable as any
    const result = resultTable.$el.querySelectorAll('.el-table__row')
    const { offsetTop } = result[targetIndexes[0]] as HTMLElement
    resultTable.bodyWrapper.scrollTop = offsetTop
    // 赋值
    this.relatedErrRowIndex = targetIndexes
    this.relatedErrColumnLabel = columnLabel
  }
}
export default NoneStandard
</script>

<style lang="less" scoped>
@import '~@/styles/theme.less';
@import '~@/styles/layout.less';
.AAE_module {
  position: relative;
  box-sizing: border-box;
  padding: 20px;
  width: 100%;
  height: 100%;
  #flex(column, flex-start, flex-start);
  section {
    box-sizing: border-box;
    padding: 10px;
    width: 100%;
    margin-bottom: 20px;
    border-radius: 5px;
    #color(background-color, --module-bg-color);
    #shadow-color(0, 2px, 12px, 0, --primary-shadow-color);
  }
  .item {
    #flex(row, center, flex-start);
    span {
      font-size: 14px;
      margin-right: 10px;
      white-space: nowrap;
      #color(color, --primary-text-color);
    }
    .el-input,
    .el-select {
      width: 200px;
    }
  }
  .message {
    #flex(row, center, flex-start);
    .item {
      flex: 1;
    }
  }
  .table {
    flex: 1;
    min-height: 200px;
    max-height: 300px;
    overflow: auto;
    .el-table {
      height: 100%;
    }
  }
  .settings {
    flex: 1;
    width: 100%;
    margin-bottom: 0;
    #flex(column, flex-start, flex-start);
    .setting-header {
      width: 100%;
      height: 25px;
      margin-bottom: 10px;
      #flex(row, center, space-between);
      h4 {
        margin-block: 0;
        font-size: 16px;
        font-weight: 900;
        #color(color, --primary-text-color);
      }
      .buttons {
        #flex(row, center, flex-end);
        .iconfont {
          box-sizing: border-box;
          padding: 2px;
          margin-left: 5px;
          font-size: 18px;
          transition: all 0.5s ease;
          cursor: pointer;
          #color(color, --primary-text-color);
        }
        .iconfont:hover {
          color: #ffffff;
          #color(background-color, --primary-blue-color);
        }
        .is-disabled {
          cursor: not-allowed;
          #color(color, --lighter-text-color);
        }
        .is-disabled:hover {
          #color(background-color, --gray-blue-color);
        }
      }
    }
    .setting-body {
      width: 100%;
      overflow: auto;
      #flex(row, flex-start, space-between);
      .column {
        box-sizing: border-box;
        height: 100%;
        padding-right: 10px;
        margin-right: 10px;
        border-right: solid 1px;
        #flex(column, flex-start, flex-start);
        #color(border-right-color, --primary-border-color);
      }
      .column:first-child {
        max-width: 400px;
        flex: 1;
      }
      .column:nth-child(2) {
        flex: 1;
        min-width: 300px;
        overflow: auto;
        /deep/.el-table {
          height: 100%;
          margin-bottom: 5px;
          .el-table__header-wrapper {
            .el-table__header {
              .el-table__cell {
                font-size: 12px;
                font-weight: 400;
                #color(color, --primary-text-color);
              }
            }
          }
        }
      }
      .column:last-child {
        padding-right: 0;
        margin-right: 0;
        border-right: solid 0;
        width: 300px;
        .row {
          box-sizing: border-box;
          padding: 10px;
          width: 100%;
          margin-bottom: 10px;
          #flex(column, flex-start, flex-start);
          #color(background-color, --primary-bg-color);
          .title {
            margin-bottom: 5px;
            font-size: 16px;
            font-weight: 500;
            #color(color, --primary-text-color);
          }
          .el-textarea {
            width: 100%;
          }
        }
        .row:first-child {
          flex-direction: row;
          align-items: center;
          span {
            font-size: 16px;
            font-weight: 500;
            #color(color, --primary-text-color);
          }
          span:last-child {
            box-sizing: border-box;
            padding: 2px 5px;
            font-size: 14px;
          }
          .isEmpty {
            #color(color, --primary-text-color);
            #color(background-color, --primary-bg-color);
          }
          .isSuccess {
            color: #ffffff;
            #color(background-color, --primary-green-color);
          }
          .isError {
            color: #ffffff;
            #color(background-color, --primary-red-color);
          }
        }
        .row:last-child {
          margin-bottom: 0;
          overflow: auto;
          .labels {
            flex: 1;
            width: 100%;
            flex-wrap: wrap;
            align-content: flex-start;
            overflow: auto;
            #flex(row, flex-start, flex-start);
            .label {
              box-sizing: border-box;
              padding: 5px;
              margin: 5px;
              width: 100%;
              border-radius: 3px;
              font-size: 14px;
              color: #ffffff;
              #flex(row, center, space-between);
              #color(background-color, --primary-red-color);
              span {
                font-size: 12px;
                line-height: 20px;
                white-space: nowrap;
              }
            }
          }
        }
      }
    }
  }
  .popover {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 2;
    margin-bottom: 0;
    backdrop-filter: blur(10px);
    background-color: unset;
    #flex(row, center, center);
    .popover-content {
      box-sizing: border-box;
      padding: 20px;
      width: 70%;
      border-radius: 20px;
      overflow: auto;
      #color(background-color, --module-bg-color);
      #shadow-color(0, 0, 8px, 1px, --primary-shadow-color);
      #flex(column, flex-start, flex-start);
      .row {
        flex: 1;
        width: 100%;
        margin-bottom: 10px;
        #flex(column, flex-start, flex-start);
        .title {
          line-height: 30px;
          text-align: left;
        }
        .table {
          height: 330px;
          width: 100%;
        }
      }
      .row:last-child {
        margin-bottom: 0;
      }
    }
    .chart {
      width: 60%;
      height: 500px;
      #flex(row, flex-start, space-between);
      .basic-line {
        flex: 1;
        margin-right: 20px;
      }
      .checkbox-group {
        width: 350px;
        flex-wrap: wrap;
        align-content: flex-start;
        #flex(row, flex-start, flex-start);
        .el-checkbox {
          width: 40%;
          margin-bottom: 10px;
          #flex(row, center, flex-start);
        }
      }
    }
  }
  .preview-area {
    position: fixed;
    width: 350px;
    height: 300px;
    z-index: 3;
    transition: all 0.5s ease;
    flex-wrap: wrap;
    align-content: flex-start;
    overflow: auto;
    #flex(row, flex-start, flex-start);
    #color(background-color, --module-bg-color);
    .label-container {
      box-sizing: border-box;
      margin: 5px;
      flex: 1;
      padding: 5px;
      #flex(row, center, space-between);
      #color(color, --primary-text-color);
      #color(background-color, --module-bg-color);
      #shadow-color(0, 0, 4px, 1px, --primary-shadow-color);
      span {
        font-size: 12px;
        white-space: nowrap;
        margin-right: 10px;
      }
      span:last-child {
        margin-right: 0;
      }
    }
    .label-container:first-child {
      width: 100%;
      flex: unset;
      span:last-child {
        font-size: 16px;
        font-weight: 600;
        #color(color, --primary-blue-color);
      }
    }
  }
}
.opacity-enter-active,
.opacity-leave-active {
  transition: all 0.5s ease;
}
.opacity-enter,
.opacity-leave-to {
  opacity: 0;
}
.opacity-enter-to,
.opacity-leave {
  opacity: 1;
}
</style>
